/**
 * 
 */
package fr.utbm.gi.vi51.slizers.pw.gui.simulation;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.util.List;

import javax.swing.JPanel;

import fr.utbm.gi.vi51.slizers.framework.agent.Direction;
import fr.utbm.gi.vi51.slizers.framework.agent.SituatedObject;
import fr.utbm.gi.vi51.slizers.pw.agent.CreatureBody;
import fr.utbm.gi.vi51.slizers.pw.agent.CreatureBodyState;
import fr.utbm.gi.vi51.slizers.pw.environment.WorldElement;
import fr.utbm.gi.vi51.slizers.pw.environment.WorldState;

/**
 * Implementation of a GUI panel showing the world.
 * 
 * @author Tarik Belabbas
 * 
 */
public class WorldPanel extends JPanel
{
	/**
	 * Version number associated to the serializable class.
	 */
	private static final long	serialVersionUID	= 2312384976769512024L;

	/**
	 * The width of the world.
	 */
	private int				worldWidth;

	/**
	 * The height of the world.
	 */
	private int				worldHeight;

	/**
	 * The size of a cell, in pixels.
	 */
	private int				cellSize = 10;

	/**
	 * The last map of the world.
	 */
	private List< List< WorldElement > >	lastMap				= null;
	
	/**
	 * The last state of the world.
	 */
	private WorldState						lastState			= null;

	/**
	 * Constructor.
	 */
	public WorldPanel()
	{
		// Design
		setBackground( Color.WHITE );
	}
	
	/* (non-Javadoc)
	 * @see javax.swing.JComponent#paint(java.awt.Graphics)
	 */
	@Override
	public void paint( Graphics _graphics )
	{
		super.paint( _graphics );
		
		drawMap( _graphics );
		drawCreatures( _graphics );
	}
	
	/**
	 * The size of world cells.
	 * 
	 * @param _cellSize the new cell size
	 */
	public void setCellSize( int _cellSize )
	{
		this.cellSize = 10;
		this.setPreferredSize( new Dimension( this.worldWidth * this.cellSize,
				this.worldHeight * this.cellSize ) );
		setMinimumSize( new Dimension( this.worldWidth * this.cellSize,
				this.worldHeight * this.cellSize ) );
	}
	
	/**
	 * Draw the map of the world.
	 */
	private void drawMap( Graphics _graphics )
	{
		if ( this.lastMap != null )
		{
			for ( int i = 0; i < this.worldWidth; ++i )
			{
				for ( int j = 0; j < this.worldHeight; ++j )
				{
					_graphics.setColor( this.lastMap.get( i ).get( j )
							.getColor() );

					int xInPixels = getXInPixels( i );
					int yInPixels = getYInPixels( j );
					
					_graphics.fillRect( xInPixels, yInPixels, this.cellSize,
							this.cellSize );
				}
			}
		}
	}
	
	/**
	 * Returns the position of a given x in cells in pixels
	 * 
	 * @param xInCells the x position in cells
	 * @return the position in pixels
	 */
	private int getXInPixels(int xInCells){
		return ( xInCells * this.cellSize );
	}
	
	/**
	 * Returns the position of a given y in cells in pixels
	 * 
	 * @param yInCells the y position in case
	 * @return the position in pixels
	 */
	private int getYInPixels(int yInCells){
		return ( this.worldHeight - yInCells - 1 ) * this.cellSize;
		//return ( this.worldHeight * this.cellSize ) - ( ( yInCells * this.cellSize ) - 1 );
	}
	
	/**
	 * Draw the creatures in the world.
	 */
	private void drawCreatures( Graphics _graphics )
	{
		if ( this.lastState != null )
		{
			for ( SituatedObject body : this.lastState.getObjects() )
			{
				if ( body instanceof CreatureBody )
				{
					CreatureBody creature = ( CreatureBody )body;
					
					int positionX = getXInPixels( creature.getX() );
					int positionY = getYInPixels( creature.getY() );
					
					_graphics.setColor( Color.BLUE );
					
					int unitSize = this.cellSize/10;
					// Body
					_graphics.fillRect( positionX + 3*unitSize,
							positionY + 4*unitSize,
							3*unitSize,
							6*unitSize
							);
					
					_graphics.setColor( Color.ORANGE );
					
					// Head
					_graphics.fillRect( positionX + 3*unitSize,
							positionY + 2*unitSize,
							4*unitSize,
							2*unitSize
							);
					
					_graphics.setColor( Color.BLUE );
					
					if ( creature.getState() == CreatureBodyState.GLIDING )
					{	
						// Arms
						_graphics.fillRect( positionX,
								positionY + 4*unitSize,
								this.cellSize,
								2*unitSize
								);
						_graphics.setColor( Color.RED );
						
						// Umbrella
						_graphics.fillRect( positionX,
								positionY,
								this.cellSize,
								2*unitSize
								);
						_graphics.fillRect( positionX,
								positionY,
								unitSize,
								4*unitSize
								);
						_graphics.fillRect( positionX + this.cellSize - 1,
								positionY,
								unitSize,
								4*unitSize
								);
					}
					else
					{
						if( creature.getDirection() == Direction.RIGHT )
						{
							_graphics.fillRect( positionX + 6*unitSize,
									positionY + 4*unitSize,
									4*unitSize,
									2*unitSize
									);
						}
						else
						{
							_graphics.fillRect( positionX,
									positionY + 4*unitSize,
									4*unitSize,
									2*unitSize
									);
						}
					}
				}
			}
		}
	}

	/**
	 * Sets the last world state.
	 * 
	 * @param _lastState the last world state
	 */
	public void setLastState( WorldState _lastState )
	{
		this.lastState = _lastState;
	}
	
	/**
	 * Sets the last world map.
	 * 
	 * @param _lastMap the last world map
	 */
	public void setLastMap( List< List< WorldElement > > _lastMap )
	{
		this.lastMap		= _lastMap;
		this.worldWidth		= this.lastMap.size();
		this.worldHeight	= this.lastMap.get( 0 ).size();
		
		setPreferredSize( new Dimension( this.worldWidth * this.cellSize,
				this.worldHeight * this.cellSize ) );
		setMinimumSize( new Dimension( this.worldWidth * this.cellSize,
				this.worldHeight * this.cellSize ) );
	}
}

